﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace psafth.AMB
{
    public class AMBMessage
    {
        /// <summary>
        /// Version (default = 02)
        /// </summary>
        public byte Version
        {
            get;
            private set;
        }

        /// <summary>
        /// Length of record LSB
        /// </summary>
        public byte LengthLSB
        {
            get;
            private set;
        }

        /// <summary>
        /// Length of record MSB
        /// </summary>
        public byte LengthMSB
        {
            get;
            private set;
        }

        /// <summary>
        /// CRC of record LSB
        /// </summary>
        public byte ChecksumLSB
        {
            get;
            private set;
        }

        /// <summary>
        /// CRC of record MSB
        /// </summary>
        public byte ChecksumMSB
        {
            get;
            private set;
        }

        /// <summary>
        /// Flags of record LSB
        /// </summary>
        public byte FlagsLSB
        {
            get;
            private set;
        }

        /// <summary>
        /// Flags of record MSB
        /// </summary>
        public byte FlagsMSB
        {
            get;
            private set;
        }

        /// <summary>
        /// TOM (Type of Message) LSB
        /// </summary>
        public byte TypeLSB
        {
            get;
            private set;
        }

        /// <summary>
        /// TOM (Type of Message) MSB
        /// </summary>
        public byte TypeMSB
        {
            get;
            private set;
        }

        /// <summary>
        /// Fields of record
        /// </summary>
        public List<byte[]> DataRecords
        {
            get;
            private set;
        }

        public bool CRCValid
        {
            get
            {
                return true;
             //   throw new NotImplementedException();
            }
        }

        private const int ESC = 0x8d;                       // Escape character
        private const int ESCx = 0x20;                      // value to subtract from escaped char
        private const int SOR = 0x8e;                       // Start of Record
        private const int EOR = 0x8f;

        private const byte ESCxB = 0x20;
        
        // End of Record

        /// <summary>
        /// Constructs a AMBMessage from an array of bytes.
        /// </summary>
        /// <param name="byteArray"></param>
        public AMBMessage(byte[] byteArray)
        {
            this.Version = byteArray[0x01];                 // 01 - Version (default = 02)
            this.LengthLSB = byteArray[0x02];               // 02 - length of record LSB
            this.LengthMSB = byteArray[0x03];               // 03 - length of record MSB
            this.ChecksumLSB = byteArray[0x04];             // 04 - CRC of record LSB
            this.ChecksumMSB = byteArray[0x05];             // 05 - CRC of record MSB
            this.FlagsLSB = byteArray[0x06];                // 06 - Flags of record LSB
            this.FlagsMSB = byteArray[0x07];                // 07 - Flags of record MSB
            this.TypeLSB = byteArray[0x08];                 // 08 - TOR (Type of Message) LSB
            this.TypeMSB = byteArray[0x09];                 // 09 - TOR (Type of Message) MSB

            this.DataRecords = new List<byte[]>();

            List<byte> dataline = new List<byte>();

            // 10 - FORs (Fields of Record)
            // ...
            // ...
            // EOF (End of Record = 8f)

            for (int i = 0x0a; i < byteArray.Length - 1; i++)
            {
                if (byteArray[i] != EOR)
                {
                    int lor = byteArray[i + 1];

                    for (int j = i; j < i + lor + 2; j++)
                    {
                        // Unescaping
                        if (byteArray[j] == ESC)
                        {
                            j++;
                            lor++;
                            byte b = (byte)(byteArray[j] - ESCxB);
                            dataline.Add(b);
                        }
                        else
                        {
                            dataline.Add(byteArray[j]);
                        }
                    }
                    DataRecords.Add(dataline.ToArray());

                    i += lor + 1;

                    dataline.Clear();
                }
            }
        }
    }
}
